<!DOCTYPE html>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
setup(() => {
  converter = internals.typeConversions();
});

function verifyAttribute(attribute)
{
  assert_true(attribute in converter);
  assert_equals(typeof converter[attribute], "number");
  converter[attribute] = 123;
  assert_equals(converter[attribute], 123);
  converter[attribute] = 0;
  assert_equals(converter[attribute], 0);
}

function convert(attribute, value, expected)
{
  if (arguments.length < 3) {
    expected = value;
  }
  converter[attribute] = value;
  assert_equals(converter[attribute], expected);
}

function testNonNumericToNumeric(attribute)
{
  convert(attribute, false, 0);
  convert(attribute, true, 1);
  convert(attribute, '', 0);
  convert(attribute, '1', 1);
  convert(attribute, 'abc', 0);
  convert(attribute, null, 0);
  convert(attribute, undefined, 0);
}

function testNonNumericToNumericEnforceRange(attribute)
{
  convert(attribute, false, 0);
  convert(attribute, true, 1);
  convert(attribute, '', 0);
  convert(attribute, '1', 1);
  assert_throws_js(TypeError, () => { converter[attribute] = 'abc' });
  convert(attribute, null, 0);
  assert_throws_js(TypeError, () => { converter[attribute] = undefined });
}

test(() => {
  type = "testLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000);
  convert(type, -0x8001);
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000, -0x80000000);
  convert(type, 0xFFFFFFFF, -1);
  convert(type, -0x80000000);
  convert(type, -0x80000001, 0x7FFFFFFF);
  convert(type, 0xDCBA9876543210, 0x76543210);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversions of long types");

test(() => {
  type = "testEnforceRangeLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000);
  convert(type, -0x8001);
  convert(type, 0x7FFFFFFF);
  assert_throws_js(TypeError, () => { converter[type] = 0x80000000 });
  assert_throws_js(TypeError, () => { converter[type] = 0xFFFFFFFF });
  convert(type, -0x80000000);
  assert_throws_js(TypeError, () => { converter[type] = 0x80000001 });
  assert_throws_js(TypeError, () => { converter[type] = 0xDCBA9876543210 });
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  convert(type, Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversions of [EnforceRange] long types");

test(() => {
  type = "testUnsignedLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1, 0xFFFFFFFF);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80, 0xFFFFFF80);
  convert(type, -0x81, 0xFFFFFF7F);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000, 0xFFFF8000);
  convert(type, -0x8001, 0xFFFF7FFF);
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  convert(type, -0x80000000, 0x80000000);
  convert(type, -0x80000001, 0x7FFFFFFF);
  convert(type, 0xDCBA9876543210, 0x76543210);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, 0xFFFFFFFF);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversions of unsigned long types");

test(() => {
  type = "testEnforceRangeUnsignedLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  assert_throws_js(TypeError, () => { converter[type] = -1 });
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x80 });
  assert_throws_js(TypeError, () => { converter[type] = -0x81 });
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x8000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x8001 });
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x80000000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x80000001 });
  assert_throws_js(TypeError, () => { converter[type] = 0xDCBA9876543210 });
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  convert(type, Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  assert_throws_js(TypeError, () => { converter[type] = -1.99 });
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversions of [EnforceRange] unsigned long types");

test(() => {
  type = "testLongLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000);
  convert(type, -0x8001);
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  convert(type, -0x80000000);
  convert(type, -0x80000001);
  convert(type, -Math.pow(2, 53) + 1);
  convert(type, -Math.pow(2, 53));
  convert(type, Math.pow(2, 53) - 1);
  convert(type, Math.pow(2, 53));
  convert(type, 0xDCBA9876543210);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversions of long long types");

test(() => {
  type = "testEnforceRangeLongLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000);
  convert(type, -0x8001);
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  convert(type, -0x80000000);
  convert(type, -0x80000001);
  convert(type, -Math.pow(2, 53) + 1);
  assert_throws_js(TypeError, () => { converter[type] = -Math.pow(2, 53) });
  convert(type, Math.pow(2, 53) - 1);
  assert_throws_js(TypeError, () => { converter[type] = Math.pow(2, 53) + 1 });
  assert_throws_js(TypeError, () => { converter[type] = 0xDCBA9876543210 });
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] long long types");

test(() => {
  type = "testUnsignedLongLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1, 0xFFFFFFFFFFFFFFFF);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80, 0xFFFFFFFFFFFFFF80);
  convert(type, -0x81, 0xFFFFFFFFFFFFFF7F);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, -0x8000, 0xFFFFFFFFFFFF8000);
  convert(type, -0x8001, 0xFFFFFFFFFFFF7FFF);
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  convert(type, -0x80000000, 0xFFFFFFFF80000000);
  convert(type, -0x80000001, 0xFFFFFFFF7FFFFFFF);
  convert(type, -Math.pow(2, 53) + 1, Math.pow(2, 64) - Math.pow(2, 53));
  convert(type, -Math.pow(2, 53), Math.pow(2, 64) - Math.pow(2, 53));
  convert(type, Math.pow(2, 53) - 1);
  convert(type, Math.pow(2, 53));
  convert(type, 0xDCBA9876543210);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, 0xFFFFFFFFFFFFFFFF);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of unsigned long long types");

test(() => {
  type = "testEnforceRangeUnsignedLongLong";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  assert_throws_js(TypeError, () => { converter[type] = -1 });
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x80 });
  assert_throws_js(TypeError, () => { converter[type] = -0x81 });
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x8000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x8001 });
  convert(type, 0x7FFFFFFF);
  convert(type, 0x80000000);
  convert(type, 0xFFFFFFFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x80000000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x80000001 });
  assert_throws_js(TypeError, () => { converter[type] = -Math.pow(2, 53) + 1 });
  assert_throws_js(TypeError, () => { converter[type] = -Math.pow(2, 53) });
  convert(type, Math.pow(2, 53) - 1);
  assert_throws_js(TypeError, () => { converter[type] = Math.pow(2, 53) });
  assert_throws_js(TypeError, () => { converter[type] = 0xDCBA9876543210 });
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, 1.99, 1);
  assert_throws_js(TypeError, () => { converter[type] = -1.99 });
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] unsigned long long types");

test(() => {
  type = "testByte";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80, -0x80);
  convert(type, -0x7F);
  convert(type, -0x80);
  convert(type, -0x81, 0x7F);
  convert(type, 0x1234, 0x34);
  convert(type, 0xDCBA9876543210, 0x10);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  convert(type, 4660.99, 0x34);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of byte types");

test(() => {
  type = "testEnforceRangeByte";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  assert_throws_js(TypeError, () => { converter[type] = 0x80 });
  convert(type, -0x7F);
  convert(type, -0x80);
  assert_throws_js(TypeError, () => { converter[type] = -0x81 });
  assert_throws_js(TypeError, () => { converter[type] = 0x1234 });
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  assert_throws_js(TypeError, () => { converter[type] = 4660.99 });
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] byte types");

test(() => {
  type = "testOctet";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1, 0xFF);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, 0x100, 0);
  convert(type, 0x101, 1);
  convert(type, -0x80, 0x80);
  convert(type, -0x81, 0x7F);
  convert(type, 0x1234, 0x34);
  convert(type, 0xDCBA9876543210, 0x10);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, 0xFF);
  convert(type, 4660.99, 0x34);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of octet types");

test(() => {
  type = "testEnforceRangeOctet";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  assert_throws_js(TypeError, () => { converter[type] = -1 });
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  assert_throws_js(TypeError, () => { converter[type] = 0x100 });
  assert_throws_js(TypeError, () => { converter[type] = 0x101 });
  assert_throws_js(TypeError, () => { converter[type] = -0x80 });
  assert_throws_js(TypeError, () => { converter[type] = -0x81 });
  assert_throws_js(TypeError, () => { converter[type] = 0x1234 });
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  convert(type, Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  assert_throws_js(TypeError, () => { converter[type] = -1.99 });
  assert_throws_js(TypeError, () => { converter[type] = 4660.99 });
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] octet types");

test(() => {
  type = "testShort";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  convert(type, 0x8000, -0x8000);
  convert(type, 0xFFFF, -1);
  convert(type, -0x8000);
  convert(type, -0x8001, 0x7FFF);
  convert(type, 0xDCBA9876543210, 0x3210);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of short types");

test(() => {
  type = "testEnforceRangeShort";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80);
  convert(type, -0x81);
  convert(type, 0x7FFF);
  assert_throws_js(TypeError, () => { converter[type] = 0x8000 });
  assert_throws_js(TypeError, () => { converter[type] = 0xFFFF });
  convert(type, -0x8000);
  assert_throws_js(TypeError, () => { converter[type] = -0x8001 });
  assert_throws_js(TypeError, () => { converter[type] = 0xDCBA9876543210 });
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  convert(type, Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, -1);
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] short types");

test(() => {
  type = "testUnsignedShort";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  convert(type, -1, 0xFFFF);
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  convert(type, -0x80, 0xFF80);
  convert(type, -0x81, 0xFF7F);
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  convert(type, 0x10000, 0);
  convert(type, -0x8000, 0x8000);
  convert(type, -0x8001, 0x7FFF);
  convert(type, 0xDCBA9876543210, 0x3210);
  convert(type, Number.MAX_VALUE, 0);
  convert(type, Number.MIN_VALUE, 0);
  convert(type, -Number.MAX_VALUE, 0);
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  convert(type, -1.99, 0xFFFF);
  convert(type, Infinity, 0);
  convert(type, -Infinity, 0);
  convert(type, NaN, 0);
  testNonNumericToNumeric(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of unsigned short types");

test(() => {
  type = "testEnforceRangeUnsignedShort";
  verifyAttribute(type);
  convert(type, 0);
  convert(type, -0, 0);
  assert_throws_js(TypeError, () => { converter[type] = -1 });
  convert(type, 1);
  convert(type, 0x7F);
  convert(type, 0x80);
  convert(type, 0xFF);
  assert_throws_js(TypeError, () => { converter[type] = -0x80 });
  assert_throws_js(TypeError, () => { converter[type] = -0x81 });
  convert(type, 0x7FFF);
  convert(type, 0x8000);
  convert(type, 0xFFFF);
  assert_throws_js(TypeError, () => { converter[type] = 0x10000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x8000 });
  assert_throws_js(TypeError, () => { converter[type] = -0x8001 });
  convert(type, 0x3210);
  assert_throws_js(TypeError, () => { converter[type] = Number.MAX_VALUE });
  convert(type, Number.MIN_VALUE, 0);
  assert_throws_js(TypeError, () => { converter[type] = -Number.MAX_VALUE });
  convert(type, -Number.MIN_VALUE, 0);
  convert(type, 1.99, 1);
  assert_throws_js(TypeError, () => { converter[type] = -1.99 });
  assert_throws_js(TypeError, () => { converter[type] = Infinity });
  assert_throws_js(TypeError, () => { converter[type] = -Infinity });
  assert_throws_js(TypeError, () => { converter[type] = NaN });
  testNonNumericToNumericEnforceRange(type);
  assert_throws_js(Error, () => {
    converter[type] = {
      valueOf: () => { throw new Error('custom') }
    }
  });
}, "Test conversion of [EnforceRange] unsigned short types");

test(() => {
  converter.testByteString = '!@#123ABCabc\x00\x80\xFF\r\n\t';
  assert_equals(converter.testByteString, "!@#123ABCabc\x00\x80\xFF\r\n\t");
  assert_throws_js(TypeError, () => { converter.testByteString = '\u0100' });
  assert_throws_js(Error, () => {
    converter.testByteString = {
      toString: () => { throw Error() }
    }
  });
  assert_equals(converter.testByteString, "!@#123ABCabc\x00\x80\xFF\r\n\t");

  [{input: true, expected: "true"},
   {input: 123, expected: "123"},
   {input: null, expected: "null"},
   {input: undefined, expected: "undefined"}].forEach(function(test) {
    converter.testByteString = test.input;
    assert_equals(converter.testByteString, test.expected);
  });
  converter.setTestByteString('abc');
  assert_throws_js(TypeError, () => { converter.setTestByteString('\u0100') });
  assert_throws_js(TypeError, () => { converter.setTestByteString() });
  assert_equals(converter.testByteString, "abc");
}, "Test conversion of ByteString types");

test(() => {
  converter.testUSVString = '!@#123ABCabc\x00\x80\xFF\r\n\t';
  assert_equals(converter.testUSVString, "!@#123ABCabc\x00\x80\xFF\r\n\t");
  converter.testUSVString = '\u0100';
  assert_equals(converter.testUSVString, "\u0100");
  assert_throws_js(Error, () => {
    converter.testUSVString = {
      toString: () => { throw Error() }
    }
  });
  assert_equals(converter.testUSVString, "\u0100");
  [{input: "\uD800", expected: "\uFFFD"},
   {input: "\uDC00", expected: "\uFFFD"},
   {input: "\uD800\u0000", expected: "\uFFFD\u0000"},
   {input: "\uDC00\u0000", expected: "\uFFFD\u0000"},
   {input: "\uDC00\uD800", expected: "\uFFFD\uFFFD"},
   {input: "\uD834\uDD1E", expected: "\uD834\uDD1E"},
  ].forEach(function(test) {
    converter.testUSVString = test.input;
    assert_equals(converter.testUSVString, test.expected);
  });
  [{input: true, expected: "true"},
   {input: 123, expected: "123"},
   {input: null, expected: "null"},
   {input: undefined, expected: "undefined"}].forEach(function(test) {
    converter.testUSVString = test.input;
    assert_equals(converter.testUSVString, test.expected);
  });
  converter.setTestUSVString('abc');
  converter.setTestUSVString('\u0100');
  assert_throws_js(TypeError, () => { converter.setTestUSVString() });
  assert_equals(converter.testUSVString, "\u0100");
}, "Test conversion of USVString types");

test(() => {
  [{input: 123, expected: "123"},
   {input: true, expected: "true"},
   {input: false, expected: "false"}].forEach(function(test) {
     converter.testUSVStringOrNull = test.input;
     assert_equals(converter.testUSVStringOrNull, test.expected);
   });
  [null, undefined].forEach(function(value) {
    converter.testUSVStringOrNull = value;
    assert_equals(converter.testUSVStringOrNull, null);

    // Assign a random string to ensure the function call below really has an
    // effect.
    converter.testUSVStringOrNull = 'dummy';

    converter.setTestUSVStringOrNull(value);
    assert_equals(converter.testUSVStringOrNull, null);
  });
}, "Test conversion of nullable USVString types");
</script>
